package com.atguigu.tingshu.album.service.impl;

import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import com.alibaba.cloud.commons.lang.StringUtils;
import com.alibaba.fastjson.JSON;
import com.atguigu.tingshu.album.mapper.*;
import com.atguigu.tingshu.common.anno.CustomCache;
import com.atguigu.tingshu.common.constant.KafkaConstant;
import com.atguigu.tingshu.common.constant.RedisConstant;
import com.atguigu.tingshu.common.constant.SystemConstant;
import com.atguigu.tingshu.common.execption.GuiguException;
import com.atguigu.tingshu.common.result.ResultCodeEnum;
import com.atguigu.tingshu.common.service.KafkaService;
import com.atguigu.tingshu.common.util.AuthContextHolder;
import com.atguigu.tingshu.model.album.TrackStat;
import com.atguigu.tingshu.query.album.AlbumInfoQuery;
import com.atguigu.tingshu.vo.album.AlbumListVo;
import com.atguigu.tingshu.vo.album.AlbumStatVo;
import com.atguigu.tingshu.vo.album.TrackStatMqVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Maps;

import com.atguigu.tingshu.album.service.AlbumAttributeValueService;
import com.atguigu.tingshu.album.service.AlbumInfoService;
import com.atguigu.tingshu.model.album.AlbumAttributeValue;
import com.atguigu.tingshu.model.album.AlbumInfo;
import com.atguigu.tingshu.model.album.AlbumStat;
import com.atguigu.tingshu.vo.album.AlbumInfoVo;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RBloomFilter;
import org.redisson.api.RedissonClient;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

@Slf4j
@Service
@SuppressWarnings({"unchecked", "rawtypes"})
public class AlbumInfoServiceImpl extends ServiceImpl<AlbumInfoMapper, AlbumInfo> implements AlbumInfoService {

	@Autowired
	private AlbumInfoMapper albumInfoMapper;
	@Autowired
	private AlbumAttributeValueService albumAttributeValueService;
	@Autowired
	private AlbumStatMapper albumStatMapper;
	@Autowired
	private KafkaService kafkaService;
	@Autowired
	private TrackStatMapper trackStatMapper;
	@Autowired
	private StringRedisTemplate redisTemplate;
	@Autowired
	private RedissonClient redissonClient;


	@Transactional
	@Override
	public void saveAlbumInfo(AlbumInfoVo albumInfoVo) {
		// 	1.保存数据到基本信息表
		AlbumInfo albumInfo = new AlbumInfo();
		// 属性拷贝
		BeanUtils.copyProperties(albumInfoVo, albumInfo);
		// 设置用户ID
		albumInfo.setUserId(AuthContextHolder.getUserId());
		// TODO 设置审核通过,以后要通过后台管理更改
		albumInfo.setStatus(SystemConstant.ALBUM_STATUS_PASS);
		// 设置免费试听集数
		if (!albumInfo.getPayType().equals(SystemConstant.ALBUM_PAY_TYPE_FREE)) {
			albumInfo.setTracksForFree(5);
		}
		albumInfoMapper.insert(albumInfo);
		// 	2.保存属性值到属性值表
		if (!CollectionUtils.isEmpty(albumInfoVo.getAlbumAttributeValueVoList())) {
			saveAlbumAttributeValueList(albumInfoVo, albumInfo);
		}
		// 	3.初始化统计数据
		for (String s : List.of(SystemConstant.ALBUM_STAT_PLAY, SystemConstant.ALBUM_STAT_SUBSCRIBE, SystemConstant.ALBUM_STAT_BROWSE, SystemConstant.ALBUM_STAT_COMMENT)) {
			albumStatMapper.insert(AlbumStat
					.builder()
					.albumId(albumInfo.getId())
					.statNum(0)
					.statType(s)
					.build());
		}
		// 新增专辑,如果开放 ES 上架专辑
		if ("1".equals(albumInfo.getIsOpen()))
			kafkaService.sendMsg(KafkaConstant.QUEUE_ALBUM_UPPER, String.valueOf(albumInfo.getId()));
	}

	@Override
	public IPage<AlbumListVo> findUserAlbumPage(Integer page, Integer limit, AlbumInfoQuery albumInfoQuery) {
		IPage<AlbumListVo> iPage = new Page<>(page, limit);
		albumInfoQuery.setUserId(AuthContextHolder.getUserId());
		iPage = albumInfoMapper.findUserAlbumPage(iPage, albumInfoQuery);
		return iPage;
	}

	@Override
	@CustomCache(cacheKey = RedisConstant.CACHE_ALBUM_INFO_PREFIX+"#{#params[0]}",
			enableLock = true,
			lockName = RedisConstant.ALBUM_INFO_LOCK_PREFIX)
	public AlbumInfo getAlbumInfo(Long id) {
		RBloomFilter<Long> bloomFilter = redissonClient.getBloomFilter(RedisConstant.ALBUM_BLOOM_FILTER);
		// 布隆过滤器中不存在该专辑id,直接抛异常
		// if(Boolean.FALSE.equals(bloomFilter.contains(id)))
		// 	throw new GuiguException(ResultCodeEnum.ALBUM_NOT_EXIST);
		return getAlbumInfoById(id);
	}

	private AlbumInfo getAlbumInfoById(Long id){
		AlbumInfo albumInfo = albumInfoMapper.selectById(id);
		albumInfo.setAlbumAttributeValueVoList(albumAttributeValueService
				.list(new LambdaQueryWrapper<AlbumAttributeValue>()
						.eq(AlbumAttributeValue::getAlbumId, id)));
		return albumInfo;
	}

	@Transactional
	@Override
	public void updateAlbumInfo(AlbumInfoVo albumInfoVo, Integer albumId) {
		AlbumInfo albumInfo = albumInfoMapper.selectById(albumId);
		BeanUtils.copyProperties(albumInfoVo, albumInfo);
		albumInfoMapper.updateById(albumInfo);
		albumAttributeValueService.remove(new LambdaQueryWrapper<AlbumAttributeValue>().eq(AlbumAttributeValue::getAlbumId, albumId));
		saveAlbumAttributeValueList(albumInfoVo, albumInfo);
		// 专辑开放就上架到 ES,否则就删除
		if ("1".equals(albumInfo.getIsOpen()))
			kafkaService.sendMsg(KafkaConstant.QUEUE_ALBUM_UPPER, String.valueOf(albumInfo.getId()));
		else
			kafkaService.sendMsg(KafkaConstant.QUEUE_ALBUM_LOWER, String.valueOf(albumInfo.getId()));

	}

	/**
	 * 删除信息,属性,统计
	 *
	 * @param albumId 专辑ID
	 */
	@Override
	public void removeAlbumInfo(Long albumId) {
		albumInfoMapper.deleteById(albumId);
		albumStatMapper.delete(new LambdaQueryWrapper<AlbumStat>().eq(AlbumStat::getAlbumId, albumId));
		albumAttributeValueService.remove(new LambdaQueryWrapper<AlbumAttributeValue>().eq(AlbumAttributeValue::getAlbumId, albumId));
		// 删除时 ES 下架专辑
		kafkaService.sendMsg(KafkaConstant.QUEUE_ALBUM_LOWER, String.valueOf(albumId));
	}

	@Override
	public List<AlbumInfo> findUserAllAlbumList() {
		return albumInfoMapper.selectList(new LambdaQueryWrapper<AlbumInfo>()
				.eq(AlbumInfo::getUserId, AuthContextHolder.getUserId())
				.select(AlbumInfo::getId, AlbumInfo::getAlbumTitle));
	}

	@Override
	@CustomCache(cacheKey = RedisConstant.CACHE_ALBUM_STAT_PREFIX+"#{#params[0]}")
	public AlbumStatVo getAlbumStatByAlbumId(Long albumId) {
		return albumInfoMapper.getAlbumStatByAlbumId(albumId);
	}

	@Override
	public void updateAlbumTrackStat(TrackStatMqVo trackStatMqVo) {
		Long albumId = trackStatMqVo.getAlbumId();
		Long trackId = trackStatMqVo.getTrackId();
		String statType = trackStatMqVo.getStatType();
		Integer count = trackStatMqVo.getCount();
		// 	更新声音记录
		TrackStat trackStat = trackStatMapper.selectOne(new LambdaQueryWrapper<TrackStat>()
				.eq(TrackStat::getTrackId, trackId)
				.eq(TrackStat::getStatType, statType));
		trackStat.setStatNum(trackStat.getStatNum() + count);
		trackStatMapper.updateById(trackStat);
		if (SystemConstant.TRACK_STAT_PLAY.equals(statType)) {
			// 	更新专辑
			AlbumStat albumStat = albumStatMapper.selectOne(new LambdaQueryWrapper<AlbumStat>()
					.eq(AlbumStat::getAlbumId, albumId)
					.eq(AlbumStat::getStatType, SystemConstant.ALBUM_STAT_PLAY));
			albumStat.setStatNum(albumStat.getStatNum() + count);
			albumStatMapper.updateById(albumStat);
		}
	}



	/**
	 * 保存专辑属性信息
	 *
	 * @param albumInfoVo 传过来的VO对象
	 * @param albumInfo   专辑基本信息
	 */
	private void saveAlbumAttributeValueList(AlbumInfoVo albumInfoVo, AlbumInfo albumInfo) {
		List<AlbumAttributeValue> albumAttributeValues = albumInfoVo.getAlbumAttributeValueVoList().stream().map(albumAttributeValueVo -> {
			AlbumAttributeValue albumAttributeValue = new AlbumAttributeValue();
			albumAttributeValue.setAlbumId(albumInfo.getId());
			albumAttributeValue.setAttributeId(albumAttributeValueVo.getAttributeId());
			albumAttributeValue.setValueId(albumAttributeValueVo.getValueId());
			return albumAttributeValue;
		}).collect(Collectors.toList());
		albumAttributeValueService.saveBatch(albumAttributeValues);
	}
}
